import matplotlib.pyplot as plt
import json
import numpy as np


def read_log_file(log_file):
    process_a_start_time = {}
    process_a_end_time = {}
    process_b_start_time = {}
    process_b_end_time = {}

    with open(log_file, 'r') as file:
        for line in file:
            if "static_multistream" in line:
                parts = line.strip().split('|')
                frame_id = parts[1].split(':')[1]
                event = parts[4].split(':')
                process = event[0]
                action = event[1]
                timestamp = float(event[2])

                if process == 'ProcessA':
                    if action == 'start':
                        process_a_start_time[frame_id] = timestamp
                    elif action == 'end':
                        process_a_end_time[frame_id] = timestamp
                elif process == 'ProcessB':
                    if action == 'start':
                        process_b_start_time[frame_id] = timestamp
                    elif action == 'end':
                        process_b_end_time[frame_id] = timestamp

    return process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time


def calculate_metrics(process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time):
    process_a_durations = []
    process_b_durations = []
    frame_durations = []
    start_times = []
    end_times = []

    for frame in process_a_start_time:
        if frame in process_a_end_time and frame in process_b_start_time and frame in process_b_end_time:
            process_a_duration = process_a_end_time[frame] - process_a_start_time[frame]
            process_b_duration = process_b_end_time[frame] - process_b_start_time[frame]
            frame_duration = process_b_end_time[frame] - process_a_start_time[frame]

            process_a_durations.append(process_a_duration)
            process_b_durations.append(process_b_duration)
            frame_durations.append(frame_duration)
            start_times.append(process_a_start_time[frame])
            end_times.append(process_b_end_time[frame])

    return process_a_durations, process_b_durations, frame_durations, start_times, end_times


def get_percentiles(data, percentiles):
    return {f'P{int(p * 100)}': np.percentile(data, p * 100) for p in percentiles}


def calculate_throughput(start_times, end_times):
    total_time = max(end_times) - min(start_times)
    frame_count = len(start_times)
    throughput = frame_count / (total_time / 1000)  # frames per second
    return throughput, frame_count, total_time


def save_results(results, output_file):
    with open(output_file, 'w') as file:
        json.dump(results, file, ensure_ascii=False, indent=4)


def plot_schedule(process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time, sample_rate=1):
    frames = sorted(set(process_a_start_time.keys()).intersection(process_a_end_time.keys()).intersection(
        process_b_start_time.keys()).intersection(process_b_end_time.keys()))

    if sample_rate > 1:
        frames = frames[::sample_rate]

    process_a_starts = [process_a_start_time[frame] for frame in frames]
    process_a_ends = [process_a_end_time[frame] for frame in frames]
    process_b_starts = [process_b_start_time[frame] for frame in frames]
    process_b_ends = [process_b_end_time[frame] for frame in frames]

    plt.figure(figsize=(12, 6))

    # Plot ProcessA
    plt.fill_between(frames, process_a_starts, process_a_ends, color='blue', alpha=0.3, label='ProcessA')

    # Plot ProcessB
    plt.fill_between(frames, process_b_starts, process_b_ends, color='green', alpha=0.3, label='ProcessB')

    plt.title('ProcessA and ProcessB Schedule')
    plt.xlabel('Frame')
    plt.ylabel('Timestamp')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()

    plt.savefig('schedule_plot.png')  # Save as image file
    plt.show()


def read_log_file(log_file):
    process_a_start_time = {}
    process_a_end_time = {}
    process_b_start_time = {}
    process_b_end_time = {}

    with open(log_file, 'r') as file:
        for line in file:
            if "static_multistream" in line:
                parts = line.strip().split('|')
                frame_number = parts[1].split(':')[1]
                process_info = parts[4].split(':')
                process_name, timestamp_type, timestamp = process_info[0], process_info[1], float(process_info[2])

                if process_name == 'ProcessA':
                    if timestamp_type == 'start':
                        process_a_start_time[frame_number] = timestamp
                    elif timestamp_type == 'end':
                        process_a_end_time[frame_number] = timestamp
                elif process_name == 'ProcessB':
                    if timestamp_type == 'start':
                        process_b_start_time[frame_number] = timestamp
                    elif timestamp_type == 'end':
                        process_b_end_time[frame_number] = timestamp

    return process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time


if __name__ == "__main__":
    log_file = 'trace_analysis.log'

    process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time = read_log_file(log_file)

    plot_schedule(process_a_start_time, process_a_end_time, process_b_start_time, process_b_end_time, sample_rate=10)
